//
//  EOCPerson.m
//  MacTestProject
//
//  Created by LiuLichen on 2022/4/26.
//

#import "EOCPerson.h"

@implementation EOCPerson {
    NSMutableSet* _friends;
}

- (id) init {
    if (self = [super init]) {
        _firstName = @"";
        _lastName = @"";
    }
    return self;
}

- (id) initWithFirstName:(NSString *)firstName andLastname:(NSString *)lastName {
    if ((self = [super init])) {
        _firstName = [firstName copy];
        _lastName = [lastName copy];
        _friends = [NSMutableSet new];
    }
    return self;
}

- (void) addFriend:(EOCPerson *)person {
    [_friends addObject:person];
}

- (void) removeFriend:(EOCPerson *)person {
    [_friends removeObject:person];
}

- (id) copyWithZone:(NSZone *)zone {
    EOCPerson* copy = [[[self class] allocWithZone:zone]
                       initWithFirstName:self.firstName andLastname:self.lastName];
    copy->_friends = [_friends mutableCopy];
    return copy;
}

- (id) deepCopy {
    EOCPerson* copy = [[[self class] alloc]
                       initWithFirstName:_firstName andLastname:_lastName];
    copy->_friends = [[NSMutableSet alloc] initWithSet:_friends copyItems:YES];
    return copy;
}

- (NSString*) description {
    return [NSString stringWithFormat: @"<%@: %p, %@",
            [self class],
            self,
            @{
                @"firstName": _firstName,
                @"lastName": _lastName
            }];
}

+ (EOCPerson*) newPerson {
    EOCPerson* person = [[EOCPerson alloc] init];
    return person;
    /**
     The method name begins with 'new', and since 'person' already has an unbalanced + 1 retain count
     from the 'alloc', no retains, releases, or autoreleases are required when returning.
     */
}

+ (EOCPerson*) somePerson {
    EOCPerson* person = [[EOCPerson alloc] init];
    return person;
    /**
     The method does not begin with one of the 'owning' prefixes, therefore ARC will add an autorelease
     when returning 'person'.
     The equivalent manual reference counting statement is:
        return [person autorelease];
     */
}

- (void) doSomeThing {
    EOCPerson* p1 = [EOCPerson newPerson];
    // ...
    EOCPerson* p2 = [EOCPerson somePerson];
    // ...

    /**
     At this point, 'p1' and 'p2' go out of scope, therefore ARC needs to clean them up as required.
     - 'p1' was returned as owned by this block of code, so it needs to be released.
     - 'p2' was returned not owned by this block of code, so it does not need to be released.
     The euqivalent manual reference counting cleanup code is:
        [p1 release];
     */
}

@end
